package view;

import java.applet.Applet;
import java.awt.Color;
import java.awt.Cursor;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.Point;
import java.awt.Toolkit;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.MemoryImageSource;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Observable;
import java.util.Random;
import java.util.Set;


import model.Sprite;

import controller.Events;

public class MenuHandler extends Observable implements ScreenHandler,KeyListener,MouseListener,MouseMotionListener {

	
	//final static Object o = new Object();
	static MenuHandler singleton;
	
	public static MenuHandler getInstance(Applet applet){
		synchronized(MenuHandler.class){
			if(singleton == null){
				return new MenuHandler(applet);
			}else{
				return singleton;
			}
		}
	}
	
	

	List<String> menus = new ArrayList<String>();
	Set<Sprite> spritesToRender = new HashSet<Sprite>(); 
	Sprite cursor;
	Cursor transparentCursor;
	Applet ts;
	int activeMenu=0;

	
	
	private MenuHandler(Applet applet){
		
		synchronized(MenuHandler.class){
			singleton = this;
		}
		
		this.ts=applet;
		
		try{
			cursor = new Sprite("../data/image/hero.png");
		}catch (IOException ioe) {
			System.out.println("MenuHandler: can't load cursor image !");
		}catch (Exception e) {
			// TODO: handle exception
		}
		
		int[] pixels = new int[16 * 16];
        Image image = Toolkit.getDefaultToolkit().createImage(
                new MemoryImageSource(16, 16, pixels, 0, 16));
        transparentCursor =
                Toolkit.getDefaultToolkit().createCustomCursor
                     (image, new Point(0, 0), "invisibleCursor");
		
		cursor.setPosition(-50,-50);
		spritesToRender.add(cursor);
		
		menus.add("Start");
		menus.add("Options");
		menus.add("");
		menus.add("Quit game");
		
		selectMenuEntry(0);
		
	}
	
	
	@Override
	public void paint(Image img) {
		Graphics g = img.getGraphics();
		g.setColor( Color.black ); 
		g.fillRect( 0, 0, img.getWidth(null), img.getHeight(null) );
		
		renderMenus(g);
		renderSprites(g);
		
	}

	private void renderMenus(Graphics g){
		Random rnd = new Random();
		Color rndColor = new Color(rnd.nextInt(255),rnd.nextInt(255),rnd.nextInt(255));
		g.setColor( rndColor );
		g.setFont(new Font("Courier",Font.BOLD,25));
		
		
		int i=0;
		for(String menu : menus){
			g.drawChars(menu.toCharArray(), 0, menu.length(), 120, 140+(i++)*40);
		}
	}
	private void renderSprites(Graphics g){
		for(Sprite s: spritesToRender){
			  g.drawImage(s.getImage().getImage(),s.getPosition()[0],s.getPosition()[1],null);  
		  }
	}
	private void hideMouseCursor(){
		ts.setCursor(transparentCursor);
	}
	private void showMouseCursor(){
		ts.setCursor(new Cursor(Cursor.DEFAULT_CURSOR));
	}
	
	private void selectMenuEntry(int menuNumber){
		//for selecting a menu entry, we place the hero sprite right ahead of it.

		//if the menu selected is a void menu, we step over it !
		if(menuNumber>=0 && menuNumber<=menus.size()-1 && menus.get(menuNumber).equals("")){
			//System.out.println("stepping over void menu !");
			menuNumber+=menuNumber-activeMenu;
		}
		
		//we avoid to be outside of the menu:
		if(menuNumber<0)activeMenu=0;
		else if(menuNumber>menus.size()-1)activeMenu=menus.size()-1;
		else activeMenu=menuNumber;
		//System.out.println(menuNumber+">>"+activeMenu+" | "+menus.get(activeMenu));
		
		cursor.setPosition(85,115+activeMenu*40);
	}
	
	private void activateMenuentry(int menuNumber){
		String menuItem = menus.get(menuNumber);
		
		if(menuItem.equals("Start")){
			//System.out.println("notify Obs");
			setChanged();
			notifyObservers(Events.START_GAME);
		}else if(menuItem.equals("Quit game")){
			setChanged();
			notifyObservers(Events.QUIT_GAME);
		}
	}
	
	@Override
	public void repaint(Image i) {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void pause() {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void reset() {
		//puts the selector and the active menu back to the initial location
		activeMenu=0;
		cursor.setPosition(85,115+activeMenu*40);
	}

	@Override
	public void start() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void stop() {
		// TODO Auto-generated method stub
		
	}

	@Override
	public void keyPressed(KeyEvent ke) {
		// TODO Auto-generated method stub

		if(ke.getKeyCode()==KeyEvent.VK_UP)selectMenuEntry(activeMenu-1);
		if(ke.getKeyCode()==KeyEvent.VK_DOWN)selectMenuEntry(activeMenu+1);
		if(ke.getKeyCode()==KeyEvent.VK_ENTER)activateMenuentry(activeMenu);
	}

	@Override
	public void keyReleased(KeyEvent ke) {
		// TODO Auto-generated method stub
	}

	@Override
	public void keyTyped(KeyEvent ke) {
		// TODO Auto-generated method stub
	}


	@Override
	public void mouseClicked(MouseEvent me) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mouseEntered(MouseEvent arg0) {
		// TODO Auto-generated method stub
		hideMouseCursor();
	}


	@Override
	public void mouseExited(MouseEvent arg0) {
		// TODO Auto-generated method stub
		showMouseCursor();
	}


	@Override
	public void mousePressed(MouseEvent arg0) {
		// TODO Auto-generated method stub
		hideMouseCursor();
		
	}


	@Override
	public void mouseReleased(MouseEvent arg0) {
		// TODO Auto-generated method stub
		
	}


	@Override
	public void mouseDragged(MouseEvent me) {
		// TODO Auto-generated method stub
		//cursor.setPosition(me.getX(),me.getY());
	}


	@Override
	public void mouseMoved(MouseEvent me) {
		// TODO Auto-generated method stub
		//cursor.setPosition(me.getX(),me.getY());
	}

}
